/**
 * 开发环境配置：代码运行即可
 * 运行项目指令
 * webpack: 会将打包结果输出出去
 * npx webpack-dev-server 只会在内存中编译打包，没有输出
 */

/**
 * HRM：hot module replacement 热模块替换/模块热替换
 * 作用：一个模块发生变化，只会重新打包这一个模块（而不是打包所有模块）
 *  极大提升构建速度
 * 
 * 样式文件：可以使用HRM功能，因为style-loader内部实现了（生产环境需要抽离出css成单独文件）
 * js文件：默认没有HRM功能
 *      --> 修改js代码，添加支持HRM功能的代码
 *      注意：HRM功能对js的处理，只能处理非入口js文件的其他文件【入口文件无法实现HRM功能】
 * HTML: 默认不能使用HMR功能，同时导致html文件不能让更新了（因为只有一个HTML文件，不需要做HRM）
 *  解决： 修改entry入口（写成数组形式），将html文件引入
 *  
 */


 /**
  * source-map: 一种提供源代码到构建后代码映射的技术（如果构建后代码出错（多个模块的代码被整合到一个模块中，无法排查错误），通过映射可以追踪源代码的错误）
  * 开启：devtool: 'source-map'
  * [inline- | hidden- | eval-][nosources-][cheap-[module-]]source-map
  * source-map:
  *   能追踪到错误代码准确信息和源代码的错误位置 【包括行和列的错误】
  * inline-source-map ：
  *   能追踪到错误代码准确信息和源代码的错误位置
  *   1.构建在打包js文件之内，不单独生成map文件，构建速度更快
  *   2. 只生成一个内联source-map
  * hidden-source-map：外部，生成map文件
  *   能追踪到错误代码准确信息， 没有错误位置   【防止源代码泄露】
  *   不能追踪源代码错误，只能提示到构建后代码的错误位置
  * eval-source-map：内连
  *   能追踪到错误代码准确信息和源代码的错误位置
  *   1. 每一个文件都生成一个对应的source-map, 都在eval函数中
  * nosources-source-map: 外部
  *   能找到错误代码准确信息，但是没有任何源代码信息  [防止源代码泄露]
  * cheap-source-map: 外部
  *   能追踪到错误代码准确信息和源代码的错误位置【只能精确到行，不能精确到列】
  * cheap-moudle-source-map:
  *   能追踪到错误代码准确信息和源代码的错误位置
  *   且moule会将loader的source map加入
  * 
  *   开发环境：速度快，调试更友好 
  *     速度快（eval > inline > cheap）
  *     eval-cheap-source-map > eval-source-map 
  *     调试友好
  *       srouce-map > cheap-moule-source-map > cheap-source-map
  *     结论 -- eval-source-map :调试最友好【vue脚手架使用】
  *           (性能更友好、更快更精确就是eval-cheap-module-source-map)
  *     
  *   生产环境：代码是否隐藏，调试要不要更友好
  *     内联会让代码体积变大，所以在生产环境不使用内联
  *     nosources-source-map  //彻底隐藏
  *     hidden-source-map //隐藏源代码，会提示构建后代码错误信息
  * 
  *     结论：不考虑隐藏源代码直接使用 source-map/cheap-module-source-map
  * 
  * 开发：eval-source-map, 生产 source-map
  */

const path = require('path')
// const { resolve } = require('path')
//const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
//该配置文件，就是一个JS文件，通过NODE的模块操作，向外暴露一个配置对象
// 基于nodejs平台运行的，模块化默认采用commonjs
module.exports = {
  //手动指定入口和出口文件
  // entry: path.join(__dirname, './src/js/index.js'), //入口：表示要使用webpack打包哪个文件，可以是字符串/数组/对象，这里入口只有一个，所以写一个字符串即可
  entry: ['./src/js/index.js', './src/index.html'],
  //出口：通常为对象，至少包含两个属性 path 和 filename
  output: {
    //输出配置文件
    //path: path.join(__dirname,'./dist'), //指定打包好的文件，输出到哪个目中去
    //__dirname:node上下文全局变量，保存当前文件所在的绝对路径
    //resolve: 将当前文件路径和指定文件拼成绝对路径
    path: path.resolve(__dirname, './dist'),
    filename: 'js/bundle.js' //指定输出的文件名称
    //涉及到url的文件将自动添加一个路径dist/, 便于在文件在打包后处于dist目录，解决index.html文件在src目录时对文件的引用路径不正确
    //（当index.html文件也在在dist目录时，则不需要此配置项）
    //publicPath: 'dist/'
  },
  // loader配置
  module: {
    rules: [
      {
        // \. 转义.
        // 处理css资源
        test: /\.css$/,
        //css loader只负责加载css文件,不负责解析生效
        //style-loader负责将样式添加到DOM中使其生效（创建style标签）
        //使用多个loader 从右向左执行（或者竖排从下到上）
        use: ['style-loader', 'css-loader']
      },
      { // 处理less资源
        test: /\.less$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader'
          },
          {
            // less文件编译成css
            loader: 'less-loader'
          }
        ]
      },
      {
        //jpg和jpeg是一样的，早期的dos操作系统文件后缀名只允许存在3位
        // 处理图片资源
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader', // url-loader 依赖file-loader,是对file-loader的一些优化（压缩图片）
            options: {
              // 当加载的图片，小于limit时，会将图片编译成base64字符串形式,直接用url-loader来加载，（base64本身是字符串，不需要单独的文件来存储，或者说打包）
              // 优点：减少请求的数量（减轻服务器压力）
              //file-loader不需要特别配置，安装即可
              //当大于limit，需要file-loader模块来进行加载（完整的图片需要打包，在dist目录会通过哈希自动生成一个随机的图片名字32位hash值（生成哈希的目的，防止重复））
              limit: 8196, //或者8*1024默认为8kb
              // 配置打包后图片的路径和名字，名字必须用 [name] 表示, 此时name是一个变量，会获取原来图片的名字。若直接img/name,则打包后的图片就会叫name
              //[hash:8]取图片的hash的前10位
              // [ext] 取文件的原扩展名
              name: 'img/[name].[hash:8].[ext]',
              // 默认处理不了html中img图片（img标签）
              // 问题：url-loader默认使用es6模块化解析，而html-loader引入图片是commonjs
              // 解释时会出问题：[object Module]
              // 解决：关闭url-loader的es6模块化，使用commonjs解析
              esModule: false,
              outputPath: 'imgs' // 打包到imgs目录下
            }
          }
        ]
      },
        
      { 
        // 处理html文件的img图片（负责引入img，从而能被url-loader进行处理）
        test: /\.html$/,
        loader: 'html-loader'
      },

      { // 处理js资源
        test: /\.js$/,
        // 排除nodemodules中的JS文件
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            //presets: ['@babel/preset-env']  会找额外的配置文件
            // presets: ['es2015'] //es2015不需要额外babel配置文件
            presets: [
              [
                '@babel/preset-env',
                {
                  useBuiltIns: 'usage',
                  corejs: {
                    version: 3
                  },
                  targets: {
                    chrome: '60',
                    firefox: '60',
                    ie: '9',
                    safari: '10',
                    edge: '17'
                  }
                }
              ]
            ]
          },
          
        }
      },
      // 打包其他资源（除了html/js/css资源以外的资源）
      {
        exclude: /\.(css|js|html|less|jpg|png|gif)$/,
        loader: 'file-loader',
        options: {
          outputPath: 'media',
          name: '[hash: 10].[ext]'
        }
      }
      // {
      //   test: /\.vue$/,
      //   use: ['vue-loader']
      // }
    ]
  },
  // resolve: {
  //   // alias:别名
  //   alias: {
  //     vue$: 'vue/dist/vue.esm.js'
  //   },
  //   // 省略文件扩展名
  //   extensions: ['.js', '.vue']
  // },
  plugins: [
    // new webpack.BannerPlugin('最终版权归*风度万人迷*所有'),
    // 功能：默认会创建一个空的HTML，引入打包输出的所有资源，解决HTML资源的问题
    
    new HtmlWebpackPlugin({
      // 指定一个模板
      // './src/index.html'
      template: './src/index.html' //以根目录下的index.html为模板复制自动生成打包的dist文件
    })
    // new uglifyJsPlugin()
  ],
  mode: 'development',
  // 开发服务器：用来自动化（自动化编译，自动打开浏览器，自动刷新浏览器）
  // 特点：只会在内存中编译打包，不会有任何输出
  // 指令：webpack-dev-server[需要安装webpack-dev-server包]
  // 启动指令：npx webpack-dev-server [局部使用命令npx]
  // 解决开发环境自动化问题
  devServer: {
    //路径（服务的文件夹）
    contentBase: path.resolve(__dirname, 'build'),
    // 启动gzip压缩，代码更小
    compress: true,
    //是否实时监听
    inline: true,
    // 端口号
    port: 3000,
    // 自动打开本地默认浏览器
    open: true,
    // devserver内部集成了HRM功能
    // 修改webpack配置，新配置要想生效，必须重启webpack
    hot: true
  },
  devtool: 'eval-source-map'
}
